home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
x2ftp
/
msdos
/
formats
/
ss0288
/
ss0288_6.txt
< prev
Wrap
Text File
|
1992-06-01
|
20KB
|
514 lines
C4H OR C5H LINSYM--SYMBOL LINE NUMBERS RECORD
=============================================
Description
-----------
This record will be used to output line numbers for functions
specified through COMDAT records. Each LINSYM record is associated
with a preceding COMDAT record.
History
-------
This record is a Microsoft extension for C 7.0.
Record Format
-------------
1 2 1 1 or 2 2 2 or 4 1
C4 Record Flags Public Line Line Checksum
or Length Name Number Number
C5 Index Offset
<---repeated--->
Flags Field
-----------
This field contains one defined bit:
01H Continuation bit. If clear, this COMDAT record establishes a
new instance of the COMDAT variable; otherwise, the data is a
continuation of the previous COMDAT of the symbol.
Public Name Index Field
-----------------------
A regular logical name index, indicating the name of the base of the
LINSYM record.
Line Number Field
-----------------
An unsigned number in the range 0 to 65,535.
Line Number Offset Field
------------------------
The offset relative to the base specified by the symbol name base. The
size of this field depends on the record type.
NOTES
Record type C5H is identical to C4H except that the Line Number
Offset field is 4 bytes instead of 2.
This record is used to output line numbers for functions specified
through COMDAT records. Often, the residing segment as well as the
relative offsets of such functions is unknown at compile time, in
that the linker is the final arbiter of such information. For such
cases, the compiler will generate this record to specify the line
number/offset pairs relative to a symbolic name.
This record will also be used to discard duplicate LINNUM
information. If the linker encounters two or more LINSYM records
with matching symbolic names (corresponding to multiple COMDAT
records with the same name), the linker will keep the one that
corresponds to the retained COMDAT.
LINSYM records must follow the COMDATs to which they refer. A LINSYM
on a given symbol refers to the most recent COMDAT on the same
symbol.
LINSYMs inherit the "localness" of their COMDATs.
C6H ALIAS--ALIAS DEFINITION RECORD
==================================
Description
-----------
This record has been introduced to support link-time aliasing, a
method by which compilers or assemblers may direct the linker to
substitute all references to one symbol for another.
History
-------
The record is a Microsoft extension for FORTRAN version 5.1 (LINK
version 5.13).
Record Format
-------------
1 2 <variable> <variable> 1
C6 Record Length Alias Name Substitute Name Checksum
<-----------repeated--------->
Alias Name Field
----------------
A regular length-preceded name of the alias symbol.
Substitute Name Field
---------------------
A regular length-preceded name of the substitute symbol.
NOTES
This record consists of two symbolic names: the alias symbol and the
substitute symbol. The alias symbol behaves very much like a PUBDEF
in that it must be unique. If a PUBDEF of an alias symbol is
encountered later, the PUBDEF overrides the alias. If another ALIAS
record with a different substitute symbol is encountered, a warning
is emitted by the linker, and the second substitute symbol is used.
When attempting to satisfy an external reference, if an ALIAS record
whose alias symbol matches is found, the linker will halt the search
for alias symbol definitions and will attempt to satisfy the
reference with the substitute symbol.
All ALIAS records must appear before the LINK Pass 2 record.
C8H OR C9H NBKPAT--NAMED BACKPATCH RECORD
=========================================
Description
-----------
The Named Backpatch record is similar to a BAKPAT record, except that
it refers to a COMDAT record, by logical name index, rather than an
LIDATA or LEDATA record. NBKPAT records must immediately follow the
COMDAT/FIXUPP block to which they refer.
History
-------
This record is a Microsoft extension for C 7.0.
Record Format
-------------
1 2 1 1 or 2 2 or 4 2 or 4 1
C8 Record Location Public Offset Value Checksum
or C9 Length Type Name
<---repeated--->
Location Type Field
-------------------
Type of location to be patched; the only valid values are:
0 8-bit byte
1 16-bit word
2 32-bit double word, record type C9H only
Public Name Index Field
-----------------------
Regular logical name index of the COMDAT record to be back patched.
Offset and Value Fields
-----------------------
These fields are 32 bits for record type C8H, 16 bits for C9H.
The Offset field specifies the location to be patched, as an offset
into the COMDAT.
The associated Value field is added to the location being patched
(unsigned addition, ignoring overflow). The Value field is a fixed
length (16 bits or 32 bits, depending on the record type) to make
object module processing easier.
CAH LLNAMES--LOCAL LOGICAL NAMES DEFINITION RECORD
==================================================
Description
-----------
The LLNAMES record is a list of local names that can be referenced by
subsequent SEGDEF and GRPDEF records in the object module.
The names are ordered by their occurrence, with the names in LNAMES
records and referenced by index from subsequent records. More than one
LNAMES and LLNAMES record may appear. The names themselves are used as
segment, class, group, overlay, COMDAT, and selector names.
History
-------
This record is a Microsoft extension for C 7.0.
Record Format
-------------
1 2 1 <--String Length--> 1
CA Record String Name Checksum
Length Length String
<----------repeated--------->
Each name appears in <count, char> format, and a null name is valid.
The character set is ASCII. Names can be up to 254 characters long.
NOTE: Any LLNAMES records in an object module must appear before the
records that refer to them.
APPENDIX 1: CODEVIEW EXTENSIONS
===============================
Calling the following information "CodeView's OMF" is a misnomer,
since CodeView actually does very little to extend the OMF. Most
CodeView information is stored within the confines of the existing
OMF, except where noted below.
CodeView information is stored on a per-module basis in specially-
named logical segments. These segments are defined in the usual way
(SEGDEF records), but LINK handles them specially, and they do not end
up as segments in the .EXE file. These segment names are reserved:
Segment Name Class Name Combine Type
------------ ---------- ------------
$$TYPES DEBTYP Private
$$SYMBOLS DEBSYM Private
The segment $$IMPORT should also be considered a reserved name,
although it is not used anymore. This segment was not part of any
object files but was emitted by the linker to get the loader to
automatically do fixups for CodeView information. The linker emitted a
standard set of imports, not just ones referenced by the program being
linked. Use of this segment may be revisited in the future.
CodeView-specific data is stored in LEDATA records for the $$TYPES and
$$SYMBOLS segments, in various proprietary formats. The $$TYPES
segment contains information on user-defined variable types; $$SYMBOLS
contains information about nonpublic symbols: stack, local, procedure,
block start, constant, and register symbols and code labels.
For instantiated functions in C 7.0, symbol information for CodeView
will be output in COMDAT records that refer to segment $$SYMBOLS and
have decorated names based on the function names. Type information
will still go into the $$TYPES segment in LEDATA records.
All OMF records that specify a Type Index field, including EXTDEF,
PUBDEF, and COMDEF records, use proprietary CodeView values. Since
many types are common, Type Index values in the range 0 through 511
(1FFH) are reserved for a set of predefined primitive types. Indexes
in the range 512 through 32767 (200H-7FFFH) index into the set of type
definitions in the module's $$TYPES segment, offset by 512. Thus 512
is the first new type, 513 the second, and so on.
APPENDIX 2: MICROSOFT MS-DOS LIBRARY FORMAT
===========================================
Libraries under MS-DOS are always multiples of 512-byte blocks.
The first record in the library is a header. This first record looks
very much like any other Microsoft object module format record.
Library Header Record (<n> bytes)
---------------------------------
1 2 4 2 1 <n - 10>
Type Record Length Dictionary Dictionary Flags Padding
Offest Size
(F0H) (Page Size Minus 3) in Blocks
The first byte of the record identifies the record's type, and the
next two bytes specify the number of bytes remaining in the record.
Note that this word field is byte-swapped (that is, the low-order
byte precedes the high-order byte). The record type for this
library header is F0H (240 decimal).
The Record Length field specifies the page size within the library.
Modules in a library always start at the beginning of a page. Page
size is determined by adding three to the value in the Record
Length field (thus the header record always occupies exactly one
page). Legal values for the page size are given by 2 to the <n>,
where <n> is greater than or equal to 4 and less than or equal to
15.
The four bytes immediately following the Record Length field are a
byte-swapped long integer specifying the byte offset within the
library of the first byte of the first block of the dictionary.
The next two bytes are a byte-swapped word field that specifies the
number of blocks in the dictionary. (The MS-DOS Library Manager
cannot create a library whose dictionary would require more than
251 512-byte pages.)
The next byte contains flags describing the library. The current
flag definition is:
0x01 = case sensitive (applies to both regular and extended
dictionaries)
All other values are reserved for future use and should be 0.
The remaining bytes in the library header record are not
significant. This record deviates from the typical Microsoft OMF
record in that the last byte is not used as a checksum on the rest
of the record.
Immediately following the header is the first object module in the
library. It, in turn, is succeeded by all other object modules in the
library. Each module is in Microsoft OMF (that is, it starts with a
LHEADR record and ends with a MODEND record). Individual modules are
aligned so as to begin at the beginning of a new page. If, as is
commonly the case, a module does not occupy a number of bytes that is
exactly a multiple of the page size, then its last block will be
padded with as many null bytes as are required to fill it.
Following the last object module in the library is a record that
serves as a marker between the object modules and the dictionary. It
also resembles a Microsoft OMF record.
Library End Record (marks end of objects and beginning of
dictionary)
1 2 <n>
Type (F1H) Record Length Padding
The record's Type field contains F1H (241 decimal), and its Record
Length field is set so that the dictionary begins on a 512-byte
boundary. The record contains no further useful information; the
remaining bytes are insignificant. As with the library header, the
last byte is not a checksum.
Dictionary
----------
The remaining blocks in the library compose the dictionary. The number
of blocks in the dictionary is given in the library header. Note that
there should always be a prime number of blocks in the dictionary.
The dictionary is a hashed index to the library. Public symbols are
essentially hashed twice, though in fact, both hash indexes are
produced simultaneously. The first hash index, the block index, is
used to determine a block within the dictionary in which to place the
symbol. The second hash index, the bucket index, is used to choose a
bucket within the block for the symbol. Blocks always have 37 buckets;
they are the first 37 bytes of each block. If a bucket is full, it
contains a nonzero value that points to the text of the symbol. To
actually find the symbol, take the bucket value, multiply it by two,
and use the resulting number as a byte offset from the beginning of
the block.
Collisions (that is, two or more distinct symbols hashing to the same
block and bucket in the dictionary) are resolved by a technique known
as linear open addressing. At the same time the hash indexes are
produced, two hash deltas are also produced. If a symbol collides with
a symbol already installed in the dictionary, the librarian attempts
to find an empty bucket for it by adding the bucket delta to the
bucket index and using the result mod 37 as a new bucket index. If
this new bucket index points to a bucket that is empty, the librarian
will install the symbol in that bucket. If the bucket is not empty,
the delta is applied repeatedly until an empty bucket is found or
until it is determined that there are no empty buckets on the block.
If the latter is the case, the block delta is added to the block
index, and the result mod the number of blocks in the dictionary is
used as a new block index. With the new block index and the original
bucket index, the sequence is repeated until an empty bucket on some
block is found.
The number of blocks and the number of buckets are prime so that no
matter what values of hash indexes and deltas are produced for a
symbol, in the worst case, all possible block-bucket combinations will
be tried. Once a free block-bucket pair has been found for a symbol,
the pair and information concerning its place of definition must be
installed. Since a bucket is a single byte pointing into a 512-byte
block, the bucket can give at best a word offset within that block.
Thus, symbol entries within a dictionary must start on word
boundaries. Since bytes 0 through 36 of each dictionary block make up
the hash table, the first symbol entry will begin at byte 38
(decimal).
Dictionary Record (length is the dictionary size in 512-byte
blocks)
37 1 <variable> 2 <conditional>
HTAB FFLAG Name Block Number Align Byte
<-------------------repeated------------->
Entries consist of the following: the first byte is the length of
the symbol to follow, the following bytes are the text of the
symbol, and the last two bytes are a byte-swapped word field that
specifies the page number (counting the library header as the 0th
page) at which the module defining the symbol begins.
All entries may have at most one trailing null byte in order to
align the next entry on a word boundary.
It is possible for a dictionary block to be full without all its
buckets being used. Such will be the case, for example, if symbol
names are longer on average than nine characters each. Therefore,
there must be some way to mark a block as full so that empty
buckets will be ignored.
Byte 37 decimal (counting from 0) is reserved for this purpose. If
the block is not full, byte 37 will contain the word offset of the
beginning of free space in the block, but if the block is full,
byte 37 will contain the special value 255 decimal (FFH). Module
names are stored in the LHEADR record of each module.
Extended Dictionary
-------------------
The extended dictionary is optional and indicates dependencies between
modules in the library. Versions of LIB earlier than 3.09 do not
create an extended dictionary. The extended dictionary is placed at
the end of the library.
The dictionary is preceded by these values:
BYTE =0xF2 Extended Dictionary header
WORD length of extended dictionary in bytes excluding first three
bytes
Start of extended dictionary:
WORD number of modules in library = N
Module table, indexed by module number, with N + 1 fixed-length
entries:
WORD module page number
WORD offset from start of extended dictionary to list of required
modules
Last entry is null.
Dictionary Hashing Algorithm
----------------------------
The last part of each library file is a dictionary, which contains
indexes to all symbols in the library. The dictionary is divided into
512-byte pages. Each page consists of a 37-byte bucket table and a 475-
byte table of symbol entries.
To find the right spot in the dictionary for a given symbol, the
hashing algorithm is used. The hashing algorithm analyzes the name of
the symbol and produces two indexes: a page and a bucket index, which
together point to a single entry in the dictionary. The only problem
is that more than one symbol name can generate exactly the same
address. Because of this, the name found in the dictionary entry must
be compared with the symbol's name, and if they are not identical, a
correction to the address must be made. To make this correction
possible, the hashing algorithm, in addition to the base address
(page, bucket), also produces the correction values (delta-page, delta-
bucket), which are added to the base address if the symbol's name does
not match the name in an entry. The number of pages in the dictionary
must always be prime, so if the symbol is not found, the consecutive
adding of deltas produces the starting address again.
Below is psueudocode illustrating the hashing algorithm used by the
LIB (librarian) utility.
extern char *symbol; /* Symbol to find */
extern int dictlength; /* Dictionary length in pages */
extern int buckets; /* Number of buckets on one page */
char *pb; /* A pointer to the beginning of the symbol */
char *pe; /* " end " */
int slength; /* Length of the symbol's name */
int page_index; /* Page index */
int page_index_delta;/* Page index delta */
int page_offset; /* Page offset (bucket #) */
int page_offset_delta;/* Page offset delta */
unsigned c;
slength = strlen(symbol);
pb = symbol;
pe = symbol + slength;
page_index = 0;
page_index_delta = 0;
page_offset = 0;
page_offset_delta = 0;
while( slength-)
{
c = *(pf++) | 32; /* Convert character to lowercase */
page_index = (page_index<<2) XOR c; /* Hash */
page_offset_delta = (page_offset_delta>>2)XORc;
c = *(pe++) | 32;
page_offset = (page_offset>>2) XOR c; /* Hash */
pageiindexdelta = (page_index_delta<<2) XOR c;
}
/* Calculate page index */
page_index = page_index MODULO dictlength;
/* Calculate page index delta */
if((page_index_delta = page_index_delta MODULO dictlength) == 0)
page_index_delta = 1;
/* Calculate page offset */
page_offset = page_offset MODULO buckets;
/* Calculate page offset delta */
if( (page_offset_delta = page_offset_delta MODULO buckets) == 0)
page_offset_delta = 1;